#include <iostream>
#include <thread>
#include <ctime>
#include "myMqttClient.h"
#include "camer.hpp"
#include "pcbDetect.h"
#include "pcbDetectCtx.h"
#include "Ctrl.h"

// 用于生成 ISO8601 时间戳
std::string getISO8601Timestamp() 
{
    std::time_t now = std::time(nullptr);
    std::tm* tm_info = std::gmtime(&now);
    char buffer[256];
    std::strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%SZ", tm_info);
    return buffer;
}

/**
 * @brief 封装PCB缺陷检测结果的上报功能
 * @param handler 协议处理对象，用于Base64编码和JSON序列化
 * @param jpeg_data JPEG格式的图像数据
 * @param image_width 图像宽度（像素）
 * @param image_height 图像高度（像素）
 * @param detections 检测到的缺陷列表
 * @param rack 存储位置的货架编号
 * @param slot 存储位置的插槽编号
 * @return 成功返回编码后的上报消息，失败返回空字符串
 */
std::string packetDetectionResults(
    ProtocolHandler& handler,
    const std::vector<uchar>& jpeg_data,
    int image_width,
    int image_height,
    const std::vector<Detection>& detections,
    const std::string& model,  // 新增产品型号参数
    const std::string& batch,  // 新增批次号参数
    const std::string& serial, // 新增序列号参数
    int rack = 0,
    int slot = 0)
{
    try {
        // 检查图像数据有效性
        if (jpeg_data.empty() || image_width <= 0 || image_height <= 0) {
            throw std::invalid_argument("无效的图像数据或尺寸");
        }
        
        // 创建上报消息
        ReportMessage reportMsg;
        reportMsg.timestamp = getISO8601Timestamp();
        reportMsg.storageLocation.rack = rack;
        reportMsg.storageLocation.slot = slot;
        
        // 填充产品信息（新增）
        reportMsg.productInfo.model = model;
        reportMsg.productInfo.batch = batch;
        reportMsg.productInfo.serial = serial;
        
        std::cout << "获取到JPEG图像数据，长度: " << jpeg_data.size() << " 字节" << std::endl;
        std::cout << "产品信息 - 型号: " << model << ", 批次: " << batch << ", 序列号: " << serial << std::endl;
        
        // 填充 ReportMessage 的 image 字段
        reportMsg.image.rawData = jpeg_data;
        reportMsg.image.format = "jpeg";
        reportMsg.image.width = image_width;
        reportMsg.image.height = image_height;
        reportMsg.image.dataSize = static_cast<int>(jpeg_data.size());
        
        // 将原始 JPEG 数据编码为 Base64 缩略图
        reportMsg.image.thumbnail = handler.imageToBase64(
            reportMsg.image.rawData, 
            reportMsg.image.width, 
            reportMsg.image.height, 
            reportMsg.image.format
        );
        std::cout << "图片base64编码成功" << std::endl;
        
        // 添加缺陷信息
        for (const auto& detection : detections) {
            // 将class_id映射到DefectType（需要根据实际情况调整）
            DefectType type = static_cast<DefectType>(detection.class_id);
            
            // 生成位置描述
            std::string position = "X:" + std::to_string(detection.bbox.x) + 
                                  ",Y:" + std::to_string(detection.bbox.y) +
                                  ",W:" + std::to_string(detection.bbox.width) +
                                  ",H:" + std::to_string(detection.bbox.height);
            
            reportMsg.addDefect(type, detection.confidence, position);
        }
        
        // 编码上报消息为JSON
        std::string encodedReport = handler.encodeReportMessage(reportMsg);
        std::cout << "上报数据转json格式数据成功" << std::endl;
       // std::cout << "encodedReport=" << encodedReport <<std::endl;
        
        return encodedReport;
        
    } catch (const std::exception& e) {
        std::cerr << "上报过程发生异常: " << e.what() << std::endl;
        return "";
    }
}

int main() 
{
    //全局信息上下文
    PCBDetectionContext* pcbCtx = PCBDetectionContext::getInstance();  

    // 要订阅的主题列表
    std::vector<std::string> topics = {"pcb/control"};

    // 启动摄像头
    Camer camer("/dev/video21");   

    //初始化下位机设备
    std::unique_ptr<PCBmachine> pm = nullptr;

    // 获取 ProtocolHandler 单例实例
    ProtocolHandler& handler = ProtocolHandler::getInstance();  

    // 创建并启动客户端
    MyMqttClient client(topics, handler, pcbCtx);
    client.start();

    // 初始化检测器
    PCBDetector detector("../model/pcb_defect.onnx");

    bool flage_frist = true;
    bool flage_test = true;
    while(DeviceStatus::STOPPED != pcbCtx->getDeviceStatus())
    {
        //std::cout << "DeviceStatus = PAUSED"<<std::endl;
        if(DeviceStatus::PAUSED == pcbCtx->getDeviceStatus()){
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
            //std::cout << "DeviceStatus = PAUSED"<<std::endl;
            
            // 跳出本次循环，继续下一次迭代
            continue;           
        }
        if(flage_frist)
        {
            flage_frist = false;
            pm = std::make_unique<PCBmachine>();
            std::cout << "pm IS OK"<<std::endl;
        }
        std::cout << "DeviceStatus = RUNNING"<<std::endl;

        //获取机械状态判断是否能拍照
        while (!pm->GetImgSignal());

        //获取一张图片
        cv::Mat image;
        cv::Mat result_image;
        bool ret = camer.get_frame_encode_to_opencv(image);
        if(ret != true){
            std::cerr << "get_frame_encode_to_opencv fial!" << std::endl;
        }

        //送检测并获取检测结果
        std::vector<Detection> detections = detector.detect(image, result_image);

        //下发机械指令用于控制pcb存放指定位置
        RackSlotInfo slotInfo; 
       // if(0 == detections.size())
       if(true == flage_test)
        {
            slotInfo = pcbCtx->getAvailableGoodRackSlot(true);
            std::cout << "slotInfo = " << slotInfo. slotId << std::endl;
            pm->place(0, slotInfo.slotId);
            flage_test = false;
        }else{
            slotInfo = pcbCtx->getAvailableBadRackSlot(true);     
            pm->place(1, slotInfo.slotId);   
        }

        // 将Mat转换为JPEG格式的字节数组
        std::vector<int> params;
        params.push_back(cv::IMWRITE_JPEG_QUALITY);
        params.push_back(85);  // 质量范围0-100，数值越高质量越好
        std::vector<uchar> jpeg_data;
        bool encode_success = cv::imencode(".jpg", result_image, jpeg_data, params);
        if(encode_success != true){
            std::cerr << "cv::imencode fial!" << std::endl;
        } 

        ProductInfo proInfo = pcbCtx->getProductInfo();
        std::string encodedReport = packetDetectionResults(handler, jpeg_data, 640, 480, detections, proInfo.model, proInfo.batch, proInfo.serial, 0, 1);
       
        // 模拟向队列中添加消息以进行发布
        client.enqueueMessage("pcb/report", encodedReport);

        std::this_thread::sleep_for(std::chrono::milliseconds(10));        
    }
    
    // 停止客户端
    client.stop();
    return 0;
}